# Copyright 2024 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for the cc_args rule."""

load("//cc/toolchains:cc_toolchain_info.bzl", "ToolInfo")
load("//cc/toolchains/impl:collect.bzl", _collect_tools = "collect_tools")
load("//cc/toolchains/impl:legacy_converter.bzl", "convert_tool")
load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects")

visibility("private")

collect_tools = result_fn_wrapper(_collect_tools)
collection_result = subjects.result(subjects.collection)

collect_tool = result_fn_wrapper(
    lambda ctx, target, fail: _collect_tools(ctx, [target], fail = fail)[0],
)
tool_result = subjects.result(subjects.ToolInfo)

# Generated by native_binary.
_BIN_WRAPPER_SYMLINK = "tests/rule_based_toolchain/testdata/bin_wrapper"
_BIN_WRAPPER = "tests/rule_based_toolchain/testdata/bin_wrapper.sh"
_BIN = "tests/rule_based_toolchain/testdata/bin"
_FILE1 = "tests/rule_based_toolchain/testdata/file1"
_TOOL_DIRECTORY = "tests/rule_based_toolchain/testdata"

def _tool_test(env, target):
    tool = env.expect.that_target(target).provider(ToolInfo)
    tool.exe().short_path_equals(_BIN_WRAPPER)
    tool.execution_requirements().contains_exactly(["requires-network"])
    tool.runfiles().contains_exactly([
        _BIN_WRAPPER,
        _BIN,
    ])

    legacy = convert_tool(tool.actual)
    env.expect.that_file(legacy.tool).equals(tool.actual.exe)
    env.expect.that_collection(legacy.execution_requirements).contains_exactly(["requires-network"])
    env.expect.that_collection(legacy.with_features).contains_exactly([])

def _wrapped_tool_includes_runfiles_test(env, targets):
    tool = env.expect.that_target(targets.wrapped_tool).provider(ToolInfo)
    tool.exe().short_path_equals(_BIN_WRAPPER_SYMLINK)
    tool.runfiles().contains_exactly([
        _BIN_WRAPPER_SYMLINK,
        _BIN,
    ])

def _tool_with_allowlist_include_directories_test(env, targets):
    tool = env.expect.that_target(targets.tool_with_allowlist_include_directories).provider(ToolInfo)
    tool.allowlist_include_directories().contains_exactly([_TOOL_DIRECTORY])
    tool.runfiles().contains_at_least([
        _BIN,
        _FILE1,
    ])

def _collect_tools_collects_tools_test(env, targets):
    env.expect.that_value(
        value = collect_tools(env.ctx, [targets.tool, targets.wrapped_tool]),
        factory = collection_result,
    ).ok().contains_exactly(
        [targets.tool[ToolInfo], targets.wrapped_tool[ToolInfo]],
    ).in_order()

def _collect_tools_collects_binaries_test(env, targets):
    tool_wrapper = env.expect.that_value(
        value = collect_tool(env.ctx, targets.bin_wrapper),
        factory = tool_result,
    ).ok()
    tool_wrapper.label().equals(targets.bin_wrapper.label)
    tool_wrapper.exe().short_path_equals(_BIN_WRAPPER_SYMLINK)
    tool_wrapper.runfiles().contains_exactly([
        _BIN_WRAPPER_SYMLINK,
        _BIN,
    ])

def _collect_tools_collects_single_files_test(env, targets):
    bin = env.expect.that_value(
        value = collect_tool(env.ctx, targets.bin_filegroup),
        factory = tool_result,
        expr = "bin_filegroup",
    ).ok()
    bin.label().equals(targets.bin_filegroup.label)
    bin.exe().short_path_equals(_BIN)
    bin.runfiles().contains_exactly([_BIN])

def _collect_tools_fails_on_non_binary_test(env, targets):
    env.expect.that_value(
        value = collect_tools(env.ctx, [targets.multiple]),
        factory = collection_result,
        expr = "multiple_non_binary",
    ).err()

TARGETS = [
    "//tests/rule_based_toolchain/features:direct_constraint",
    "//tests/rule_based_toolchain/tool:tool",
    "//tests/rule_based_toolchain/tool:wrapped_tool",
    "//tests/rule_based_toolchain/tool:directory_tool",
    "//tests/rule_based_toolchain/tool:tool_with_allowlist_include_directories",
    "//tests/rule_based_toolchain/testdata:bin_wrapper",
    "//tests/rule_based_toolchain/testdata:multiple",
    "//tests/rule_based_toolchain/testdata:bin_filegroup",
    "//tests/rule_based_toolchain/testdata:bin_wrapper_filegroup",
]

# @unsorted-dict-items
TESTS = {
    "tool_test": lambda env, targets: _tool_test(env, targets.tool),
    "directory_tool_test": lambda env, targets: _tool_test(env, targets.directory_tool),
    "wrapped_tool_includes_runfiles_test": _wrapped_tool_includes_runfiles_test,
    "collect_tools_collects_tools_test": _collect_tools_collects_tools_test,
    "collect_tools_collects_binaries_test": _collect_tools_collects_binaries_test,
    "collect_tools_collects_single_files_test": _collect_tools_collects_single_files_test,
    "collect_tools_fails_on_non_binary_test": _collect_tools_fails_on_non_binary_test,
    "tool_with_allowlist_include_directories_test": _tool_with_allowlist_include_directories_test,
}
